use core::hint::unlikely;

use semx_bitops::bitmap::BitMap;

use crate::sync::spinlock::Spinlock;

struct PidMap {
    pidmap: BitMap,
    next: usize,
    max: usize,
}

static PIDMAP: Spinlock<PidMap> = Spinlock::new(PidMap { pidmap: BitMap::new(), next: 0, max: 0 });

pub(super) struct Pid(usize);

impl Pid {
    pub(super) const fn new() -> Self {
        Pid(0)
    }

    pub(super) fn create() -> Self {
        let mut map = PIDMAP.lock_irq_save();
        let mut idx = map.pidmap.bitmap_find_next_zero_bit(map.next);
        if unlikely(idx == map.max) {
            let nr = map.max;
            map.pidmap.bitmap_extend_nr(nr);
            map.max *= 2;
            idx = map.pidmap.bitmap_find_next_zero_bit(idx);
            debug_assert!(idx < map.max);
        }
        map.next = idx + 1;
        map.pidmap.bitmap_set_bit(idx);
        Pid(idx)
    }

    // 获取值
    pub(super) fn to_value(&self) -> usize {
        self.0
    }
}

impl Drop for Pid {
    fn drop(&mut self) {
        let idx = self.0;
        let mut map = PIDMAP.lock_irq_save();
        map.pidmap.bitmap_clear(idx, 1);
        if map.next > idx {
            map.next = idx;
        }
    }
}

pub(super) fn pid_init() {
    let mut map = PIDMAP.lock();
    map.pidmap.init(1024);
    map.max = 1024;
}
